/* --- 定义注解 ---

-------------------------------------

Java语言使用【@interface语法】来定义【注解(Annotation)】
它的格式如下：  */
public @interface Report {
// @interface是Annotation的class type
// @Report是Annotation
	int type() default 0;

	String level() default "info";
	String value() default "";
}

/*
‘注解’的参数类似无参数方法,可以用default设定一个默认值(强烈推荐)。最常用的参数应当命名为value。

-------------------------------------------

### 元注解 ###

有一些注解,可以修饰其他注解
这些 注解 = ‘元注解(meta annotation)’。

Java标准库已经定义了一些‘元注解’,我们只需要使用‘元注解’,通常不需要自己去编写‘元注解’。


--- @Target --- 

最常用的‘元注解’是@Target。使用@Target可以定义Annotation,让Annotation能够被应用于源码的某些位置：
	1.类或接口：ElementType.TYPE；
	2.字段：ElementType.FIELD；
	3.方法：ElementType.METHOD；
	4.构造方法：ElementType.CONSTRUCTOR；
	5.方法参数：ElementType.PARAMETER。


例如，定义注解@Report可用在Method(方法)上,我们必须添加一个@Target(ElementType.METHOD)：		*/
@Target(ELementType.METHOD)

public @interface Report {
	int type() default 0;

	String level() default "info";
	String value() default "";
}

/* 
定义注解@Report可用在Method/Field上,可以把@Target注解参数变为‘一个数组Array’
 {ElementType.METHOD,ElementType.FIELD};
例如：             */
@Target({
	Element.METHOD,
	ElementType.FIELD
})
public @interface Report {
	//...
}

/*
@Retention

另一个重要的‘元注解@Retention’定义了Annotation的生命周期：
	1.仅编译期：RetentionPolicy.SOURCE;
	2.仅class文件：RetentionPolicy.CLASS;
	3.运行期：RetentionPolicy.RUNTIME;

如果@Retention不存在,则该Annotation默认为CLASS。因为通常我们自定义的Annotation都是RUNTIME,所以,务必要加上：
	@Retention(RetentionPolicy.RUNTIME)这个‘元注解’：

‘元注解’定义‘注解’的生命周期：			*/

//生命周期(程序运行期)例子
@Retention(RetentionPolicy.RUNTIME)
public @interface Report {
	int type() default 0;

	String level() default "info";
	String value() default "";
}


/*-----------------------------------

@Repeatable

使用@Repeatable这个‘元注解’可以定义为Annotation是否可以重复。

这个‘注解应用’不是特别广泛。  */
@Repeatable(Reports.class)
@Target(ElementType.TYPE)
public @interface Report {
	int type() default 0;
	String level default "info";
	String value() default "";
}

@Target(ElementType.TYPE)
public @interface Reports {
	Report[] value();
}

// 经过@Repeatable修饰后，在某个类型声明处，就可以添加多个@Report注解：
@Report(type=1, level="debug")
@Report(type=2, level="warning")
public class Hello {
	//...
}

/*
# @Inherited(继承、继任 v.) #

使用@Inherited定义【子类】是否可继承【父类中被定义的Annotatio】。

@Inherited仅针对@Target(ElementType.TYPE)类型的annotation有效,并且仅针对class的Inherited继承,对interface的继承无效：  */
@Inherited
@Target(ElementType.TYPE)
public @interface Report {
	int type() default 0;
	String level() default "info";
	String value() default "";
}

//在使用的时候，如果一个类用到了@Report：
@Report(type=1)
public class Person {
	//...
}

//则它的子类默认也定义了该注解：
public class Student extends Person {
	//...
}

/* ------------------------------------

--- 如何定义Annotation ---

我们总结一下定义Annotation的步骤：

第一步，用@interface定义‘注解Report’：  */
public @interface Report {
}

//第二步，为注解Report,添加参数、默认值：
public @interface Report {
	int type() default 0;
	String level() default "info";
	String value() default "";
}
//把【最常用的参数】定义为【value()】，推荐所有参数都尽量设置默认值。

//第三步,用元注解配置注解：
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Report {
	int type() default 0;
	String level() default "info";
	String value() default "";
}
/*其中，必须设置@Target和@Retention.

@Retention一般设置为RUNTIME，因为我们自定义的注解通常要求在运行期读取。

一般情况下，不必写@Inherited和@Repeatable。
*/



/* -------------------------------------

--- 定义注解 の 小结 ---

1. Java使用@interface定义注解;

2. 可定义多个参数和默认值,‘核心参数’使用value名称;

3. 必须设置@Target来指定Annotation可以应用的范围;

4. 应当设置@Retention(RetentionPolicy.RUNTIME)便于运行期读取该Annotation。

5. 使用@Inherited来保证继承关系也受父级Annotation的影响。











